/**
 * @author haina.z@163.com
 * @brief store
 * @version V1.0
 */

/** Includes -----------------------------------------------------------------*/
#include "public_defs.h"
#include "csp_flash.h"
#include "../crc/crc8.h"
#include "store_flash.h"

/** Macros and constants -----------------------------------------------------*/
// 存储的消息
#define pFlashMsg                                           ((StoreMessage_t *)(pObject->pData->pBuffer))

// 当前块的起始地址
#define mFlashBlockStartAddress(address, block_size)        ((address) - ((address) % (block_size)))

// 当前块的结束地址+1，下一块的起始地址
#define mFlashBlockEndAddress(address, block_size)          ((address) - ((address) % (block_size)) + (block_size))

// 检查容量是否满足存储（等于时可以存储，但涉及到跨页则不存储）
#define mFlashCapacityIsNOK()                               ((pObject->oCtrl.u32WriteAddress + pObject->pData->u8BufSize) >= mFlashBlockEndAddress(pObject->oCtrl.u32WriteAddress, pObject->pInfo->u16BlockSize))

/** Type definitions ---------------------------------------------------------*/

/** Private variable definitions (static) ------------------------------------*/

/** Function declarations (prototypes) ---------------------------------------*/

/** Public variable definitions ----------------------------------------------*/

/** Pre-compile check --------------------------------------------------------*/

/** Code ---------------------------------------------------------------------*/

/**
 * @brief 进行对齐操作
 * @param pLen 
 * @param u8Align 
 */
void StoreFlash_privMakeAlign(uint8_t * pLen, uint8_t u8Align)
{
    uint8_t u8Tmp;

    u8Tmp = *pLen % u8Align;
    if (u8Tmp > 0)
    {
        u8Tmp = *pLen - u8Tmp;
        u8Tmp += u8Align;
        *pLen = u8Tmp;
    }
}

void StoreFlash_GetInfo(StoreFlashObject_t * pObject)
{
    uint8_t u8Block, u8HeadAlignSize;
    uint32_t u32Start, u32BolckEnd;

    // 地址初始化
    pObject->oCtrl.u32ReadAddress = pObject->pInfo->u32StartAddress;
    pObject->oCtrl.u32WriteAddress = pObject->pInfo->u32StartAddress;

    // Clear result
    pObject->oCtrl.u8Result = 0x0;

    u8HeadAlignSize = STORE_MSG_HEAD_SIZE;
    StoreFlash_privMakeAlign(&u8HeadAlignSize, pObject->pInfo->u8AlignSize);

    for (u8Block = 0; u8Block < pObject->pInfo->u8BlockNumber; u8Block++)
    {
        // Block的起始地址
        u32Start = u8Block;
        u32Start *= pObject->pInfo->u16BlockSize;
        u32Start += pObject->pInfo->u32StartAddress;
        u32BolckEnd = u32Start + pObject->pInfo->u16BlockSize;

        CspFlash_Read(u32Start, pObject->pData->pBuffer, u8HeadAlignSize);

        if (pFlashMsg->u8Type == CSP_FLASH_INVALID_VALUE)
        {
            continue; // 查找下一块
        }

        // 当前块有数据
        do
        {
            if (pFlashMsg->u8Type == pObject->pInfo->u8MessageType)
            {
                mStoreFlash_SetDataFound(pObject);

                // 更新地址
                pObject->oCtrl.u32ReadAddress = u32Start;

                pObject->oCtrl.u8ReadLength = STORE_MSG_HEAD_SIZE + pFlashMsg->u8Length;
                StoreFlash_privMakeAlign(&(pObject->oCtrl.u8ReadLength), pObject->pInfo->u8AlignSize);
                u32Start += pObject->oCtrl.u8ReadLength;

                pObject->oCtrl.u32WriteAddress = u32Start;

                // 检查这块是否结束
                if ((u32Start + u8HeadAlignSize) > u32BolckEnd)
                {
                    break;
                }

                // 读下一个信息
                CspFlash_Read(u32Start, pObject->pData->pBuffer, u8HeadAlignSize);
            }
            else
            {
                mStoreFlash_SetDataAbnormal(pObject);
                break;
            }

        } while (pFlashMsg->u8Type != CSP_FLASH_INVALID_VALUE);

        break;
    }
}

void StoreFlash_ReadData(StoreFlashObject_t * pObject)
{
    uint8_t u8Crc;

    // 找到数据
    if (mStoreFlash_DataIsFound(pObject))
    {
        if (pObject->oCtrl.u8ReadLength > pObject->pData->u8BufSize)
        {
            mStoreFlash_SetCrcError(pObject);
        }
        else
        {
            CspFlash_Read(pObject->oCtrl.u32ReadAddress, pObject->pData->pBuffer, pObject->oCtrl.u8ReadLength);

            // 判断CRC
            u8Crc = CRC8_Calculate(pFlashMsg->MsgBody, pFlashMsg->u8Length);
            if (pFlashMsg->u8CRC == u8Crc)
            {
                mStoreFlash_SetCrcOK(pObject);
            }
            else
            {
                mStoreFlash_SetCrcError(pObject);
            }
        }
    }
}

void StoreFlash_RestoreData(StoreFlashObject_t * pObject)
{
    uint8_t u8Crc;

    // 找到数据
    if (mStoreFlash_DataIsFound(pObject))
    {
        if (pObject->oCtrl.u8ReadLength > pObject->pData->u8BufSize)
        {
            mStoreFlash_SetCrcError(pObject);
        }
        else
        {
            CspFlash_Read(pObject->oCtrl.u32ReadAddress, pObject->pData->pBuffer, pObject->oCtrl.u8ReadLength);

            // 判断CRC
            u8Crc = CRC8_Calculate(pFlashMsg->MsgBody, pFlashMsg->u8Length);
            if (pFlashMsg->u8CRC == u8Crc)
            {
                mStoreFlash_SetCrcOK(pObject);
                StoreData_Restore(pObject->pData->pList, pFlashMsg->MsgBody, pFlashMsg->u8Length);
                mStoreFlash_SetRestoreSuccess(pObject);
            }
            else
            {
                mStoreFlash_SetCrcError(pObject);
            }
        }
    }
}

bool StoreFlash_DataIsChanged(StoreFlashObject_t * pObject)
{
    return StoreData_IsChanged(pObject->pData->pList, pFlashMsg->MsgBody, pObject->pData->u8Num);
}

void StoreFlash_SaveData(StoreFlashObject_t * pObject)
{
    // 是否需要擦除
    if (mStoreFlash_DataIsAbnormal(pObject)
        || mStoreFlash_CrcIsError(pObject)
        || mFlashCapacityIsNOK()
    )
    {
        if (CspFlash_Erase(pObject->oCtrl.u32WriteAddress) != true)
        {
            return;
        }

        // 更新写地址
        pObject->oCtrl.u32WriteAddress = mFlashBlockEndAddress(pObject->oCtrl.u32WriteAddress, pObject->pInfo->u16BlockSize);
        if (pObject->oCtrl.u32WriteAddress > pObject->pInfo->u32EndAddress)
        {
            pObject->oCtrl.u32WriteAddress = pObject->pInfo->u32StartAddress;
        }

        mStoreFlash_ClrDataAbnormal(pObject);
        mStoreFlash_ClrCrcError(pObject);
    }

    // 更新数据
    pFlashMsg->u8Type = pObject->pInfo->u8MessageType;
    pFlashMsg->u8Length = pObject->pData->u8Num;
    StoreData_Update(pObject->pData->pList, pFlashMsg->MsgBody, pObject->pData->u8Num);
    pFlashMsg->u8CRC = CRC8_Calculate(pFlashMsg->MsgBody, pFlashMsg->u8Length);

    // 存储
    CspFlash_Write(pObject->oCtrl.u32WriteAddress, pObject->pData->pBuffer, pObject->pData->u8BufSize);
    pObject->oCtrl.u32ReadAddress = pObject->oCtrl.u32WriteAddress;
    pObject->oCtrl.u8ReadLength = pObject->pData->u8BufSize;
    pObject->oCtrl.u32WriteAddress += pObject->pData->u8BufSize;
}

/******************************** End of file *********************************/
